package multidomain;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.text.TableView;

import controlPlane.PCE;

import tracing.Tracer;
import util.Auxiliar;
import util.Dijkstra;
import util.WeightedGraph;
import wdmsim.OXC;
import wdmsim.PhysicalTopology;
import wdmsim.WDMLink;

/**
 * Traffic Engineering Database
 * 
 * @author alissonslp
 * 
 */
public class TED {

	PhysicalTopology pt = PhysicalTopology.getInstance();
	Tracer trace = Tracer.getTracerObject();
	Domain[] domainVector = pt.getDomainVector();
	int id;
	HashMap<Domain,Vector<TableRow>> multidomainTable;	
	
	// 					Representation of domain's 0 TED
	// ---------------------------------------------------------------------------------------
	//	destination	|	inBorderNode	|		path		|		cost	| 	wavelengths
	// ---------------------------------------------------------------------------------------
	//		1		|		1			|	(0,1)			|	(18,27,14)	|	(0,1,4)
	//		1		|		2			|	(0,11,10,2,1)	|	(35,40,12)	| 	(1,5,8)
	//		2		|		5			|	(0,1,2)			|	(30,32, 28)	|	(0,1,8)	
	//		2		|		4			|	(0,11,10,2)		|	(40, 48, 60)| 	(2,3,5)
	// ---------------------------------------------------------------------------------------
	
	/**
	 * Class that represents a row of the TED
	 * @author Alisson
	 *
	 */
	public static class TableRow implements Cloneable {
		public int id;
		public int[] path;
		public int[] costs;
		public int[] wavelengths;
		public int inBorderNode;
		public int[] freeWavelengths;
		
		protected Object clone() throws CloneNotSupportedException {
		    TableRow clone = (TableRow)super.clone();
		    return clone;
		}
		
		public TableRow(int id, int borderNode, int[] freeWavelengths, int[] cost, int[] path, int[] wavelengthsBandwidth) {
			this.id = id;
			this.freeWavelengths = freeWavelengths;
			this.path = path;
			this.inBorderNode = borderNode;
			this.wavelengths = wavelengthsBandwidth;
			this.costs = cost;
		}
		
		public TableRow(int id, int borderNode, int[] freeWavelengths, int[] path, int[] wavelengthsBandwidth) {
			this.id = id;
			this.freeWavelengths = freeWavelengths;
			this.path = path;
			this.inBorderNode = borderNode;
			this.wavelengths = wavelengthsBandwidth;
		}
		
		public TableRow(TableRow tableRow) {
			if(tableRow!=null) {
				this.id = tableRow.id;
				this.costs = tableRow.costs;
				this.path = tableRow.path;
				this.wavelengths = tableRow.wavelengths;
			}
		}
		
		public TableRow(int id, int[] costs, int[] domainPath, int[] wavelengths) {
			this.id = id;
			this.costs = costs;
			this.path = domainPath;
			this.wavelengths = wavelengths;
		}
		
		/**
		 * @param dst
		 * @param id2
		 * @param availableWavelengths
		 * @param domainPath
		 */
		public TableRow(int id, int inBorderNode, int[] availableWavelengths, int[] domainPath) {
			this.id = id;
			this.inBorderNode = inBorderNode;
			this.wavelengths = availableWavelengths;
			this.path = domainPath;
		}

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public int[] getCosts() {
			return costs;
		}

		public void setCosts(int[] costs) {
			this.costs = costs;
		}

		public int getCost(int index) {
			return costs[index];
		}
		
		public void setCost(int wavelength, int cost) {
			this.costs[wavelength] = cost;
		}
		
		public int[] getPath() {
			return path;
		}

		public void setPath(int[] path) {
			this.path = path;
		}
		
		public int getPath(int i) {
			return path[i];
		}
		
		public int getInBorderNode() {
			return this.inBorderNode;
		}
		
		public void setInBorderNode(int bn) {
			this.inBorderNode = bn;
		}		
		
		public int[] getWavelengthsBandwidth() {
			return wavelengths;
		}
		
		public int getWavelengthAvailableBandwidth(int wavelength) {
			return wavelengths[wavelength];
		}

		public void setAvailableWavelengths(int[] wavelengths) {
			this.wavelengths = wavelengths;
		}
		
		public void setAvailableWavelength(int wavelength, int cost) {
			this.wavelengths[wavelength] = cost;
		}
		
		public int[] getFreeWavelengths() {
			return freeWavelengths;
		}
		
		public void setFreeWavelengths(int[] freeWavelengths) {
			this.freeWavelengths = freeWavelengths;
		}

		/**
		 * atribui a wavelength o valor do wavelenght do caminho e retorna o caminho
		 * 
		 * @param tableRowVector
		 * @param wavelength
		 * @return
		 */
		public static TableRow getBestPath(Vector<TableRow> tableRowVector, Integer wavelength) {
			int cost = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				for(int j=0; j<tableRow.wavelengths.length; j++) {
					if(tableRow.getCost(j)>=cost) {
						r = tableRowVector.get(i);
						wavelength = new Integer(j);
						cost = tableRow.getCost(j);
					}
				}
				
			}
			return r;
		}
		
		public static TableRow getBestPath(Vector<TableRow> tableRowVector) {
			int cost = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				for(int j=0; j<tableRow.wavelengths.length; j++) {
					if(tableRow.getCost(j)>=cost) {
						r = tableRowVector.get(i);
						cost = tableRow.getCost(j);
					}
				}
				
			}
			return r;
		}
		
		public static TableRow getSmallestPath(Vector<TableRow> tableRowVector, int wavelength) {
			int pathLength = Integer.MAX_VALUE;
			int cost = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getPath().length<=pathLength) {
					if(tableRow.getCost(wavelength)>cost){
						r = tableRowVector.get(i);
						pathLength = tableRow.getPath().length;
						cost = tableRow.getCost(wavelength);
					}
				}
				
			}
			return r;
		}
		public static TableRow getSmallestPath3(Vector<TableRow> tableRowVector, int wavelength) {
			int wavelengthAvailability = Integer.MAX_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
					if(tableRow.getWavelengthAvailableBandwidth(wavelength)<wavelengthAvailability){
						r = tableRowVector.get(i);
						wavelengthAvailability = tableRow.getWavelengthAvailableBandwidth(wavelength);
					}
				
				
			}
			return r;
		}
		// retorna o tableRow com menor caminho (em saltos) e maior bandwidth disponivel (nesta ordem)
		public static TableRow getSmallestPath(Vector<TableRow> tableRowVector) {
			int pathLength = Integer.MAX_VALUE;
			int wavelengthAvailability = Integer.MIN_VALUE;
			
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getPath().length<=pathLength) {
					for(int j=0; j<tableRow.wavelengths.length; j++) {					
						if(tableRow.getWavelengthAvailableBandwidth(j)>wavelengthAvailability) {
							r = tableRow;
							pathLength = tableRow.getPath().length;
							wavelengthAvailability = tableRow.getWavelengthAvailableBandwidth(j);
							
						}
					}
				}
				
			}
			return r;
		}
		
		// retorna o tableRow com menos bandwidth disponivel (nesta ordem)
		public static TableRow getSmallestPath3(Vector<TableRow> tableRowVector) {
			int wavelengthAvailability = Integer.MAX_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				
				for(int j=0; j<tableRow.wavelengths.length; j++) {					
					if(tableRow.getWavelengthAvailableBandwidth(j)<wavelengthAvailability) {
						r = tableRow;
						wavelengthAvailability = tableRow.getWavelengthAvailableBandwidth(j);
					}
				}
			}
			return r;
		}
		
		// retorna o tableRow com inBorderNode==borderNode, com menor caminho (em saltos) e maior bandwidth disponivel (nesta ordem)
		public static TableRow getSmallestPath(int borderNode, Vector<TableRow> tableRowVector) {
			int pathLength = Integer.MAX_VALUE;
			int cost = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getPath().length<=pathLength && tableRow.getInBorderNode()==borderNode) {
					for(int j=0; j<tableRow.wavelengths.length; j++) {					
						if(tableRow.getCost(j)>cost) {
							r = tableRowVector.get(i);
							pathLength = tableRow.getPath().length;
							cost = tableRow.getCost(j);
						}
					}
				}
				
			}
			return r;
		}
		
		// retorna o tableRow com inBorderNode==borderNode, com menor caminho (em saltos) e maior bandwidth disponivel (nesta ordem)
		public static TableRow getSmallestPathF(int borderNode, Vector<TableRow> tableRowVector) {
			int pathLength = Integer.MAX_VALUE;
			int freeWavelengths = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getPath().length<=pathLength && tableRow.getInBorderNode()==borderNode) {
					for(int j=0; j<tableRow.wavelengths.length; j++) {					
						//if(tableRow.getFreeWavelengths().length>freeWavelengths) {
							r = tableRowVector.get(i);
							pathLength = tableRow.getPath().length;
							freeWavelengths = tableRow.getFreeWavelengths().length;
						//}
					}
				}
				
			}
			return r;
		}
		
		// retorna o tableRow com mais bandwidth disponivel fim a fim
		public static TableRow getSmallestPath2(Vector<TableRow> tableRowVector) {
			//int pathLength = Integer.MAX_VALUE;
			int wavelengthAvailability = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				
				for(int j=0; j<tableRow.wavelengths.length; j++) {					
					if(tableRow.getWavelengthAvailableBandwidth(j)>wavelengthAvailability) {
						r = tableRowVector.get(i);
						//pathLength = tableRow.getPath().length;
						wavelengthAvailability = tableRow.getWavelengthAvailableBandwidth(j);
					}
				}
				
			}
			return r;
		}
		
		// retorna o tableRow com mais bandwidth disponivel fim a fim
		public static TableRow getShortesttPath(Vector<TableRow> tableRowVector) {
			//int pathLength = Integer.MAX_VALUE;
			int pathLength = Integer.MAX_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				
				for(int j=0; j<tableRow.wavelengths.length; j++) {					
					if(tableRow.getPath().length<pathLength) {
						r = tableRowVector.get(i);
						//pathLength = tableRow.getPath().length;
						pathLength = tableRow.getPath().length;
					}
				}
				
			}
			return r;
		}
		public static TableRow getShortestPathF(Vector<TableRow> tableRowVector) {
			int freeWavelengths = 1;
			int pathLength = Integer.MAX_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getFreeWavelengths().length>=freeWavelengths) {
					if(tableRow.getPath().length<pathLength) {
						r = tableRow;
						freeWavelengths = tableRow.getFreeWavelengths().length;
						pathLength = tableRow.getPath().length;
					}
				}
			}
			return r;
		}
		public static TableRow getShortestPathF(Vector<TableRow> tableRowVector, int wavelength) {
			int pathLength = Integer.MAX_VALUE;
			int freeWavelengths = 1;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getFreeWavelengths().length>=freeWavelengths && tableRow.getPath().length<pathLength &&
						Auxiliar.contains(tableRow.getFreeWavelengths(), wavelength)) {					
					r = tableRowVector.get(i);
					pathLength = tableRow.getPath().length;
					freeWavelengths = tableRow.getFreeWavelengths().length;
					
				} else if(i==0) {
					System.out.print("");
				}
				
			}
			return r;
		}
		public static TableRow getShortestPathF(int borderNode, Vector<TableRow> tableRowVector) {
			int pathLength = 1;
			int freeWavelengths = Integer.MIN_VALUE;
			TableRow r = null;
			for(int i=0; i<tableRowVector.size(); i++) {
				TableRow tableRow = tableRowVector.get(i);
				if(tableRow.getFreeWavelengths().length>=freeWavelengths && tableRow.getInBorderNode()==borderNode) {
					for(int j=0; j<tableRow.wavelengths.length; j++) {					
						if(tableRow.getPath().length<pathLength ) {
							r = tableRowVector.get(i);
							pathLength = tableRow.getPath().length;
							freeWavelengths = tableRow.getFreeWavelengths().length;
						}
					}
				}
				
			}
			return r;
		}
	} // end of tableRow
	
	
	///////////////////////////////////////////////////////////
	// methods of TED
	//
		
	public TED(int id) throws Exception {
		multidomainTable = new HashMap<Domain, Vector<TableRow>>();
		this.id = id;
		//generateIntradomainDatabase();
		// esse generate considera as porcoes intradominio no calculo
		generateMultidomainDatabaseF();
	}

	public HashMap<Domain,Vector<TableRow>> getMultidomainTable() {
		return this.multidomainTable;
	}
	
	public boolean hasRegister(Domain domain) {
		if(multidomainTable.containsKey(domain)) {
			return true;
			
		} else {
			return false;
		}
	}
	
	// atualiza a ted de pce de acordo com a ted de this
	public void update(PCE pce) throws Exception {
		
		/*para cada dominio 'd'
			pega o melhor tableRow de pce para this, 'bestTRPceThis'			
			pega o melhor tableRow de this para 'd', 'tr'
			pega o tableRow de pce para 'd' que passe por this, 'pceTR'
			
			para cada wavelength 'w'
				se pceTR.cost(w) > bestTRPceThis.cost(w) + tr.cost(w)
					pceTR.cost(w) = bestTRPceThis.cost(w) + tr.cost(w)
		*/
		
		// pega o melhor tableRow de pce para this, 'bestTRPceThis'
		TableRow bestTrPceThis = pce.getTed().getBestMultidomainRow(this.id);
		for(int d=0; d<pt.getNumDomains(); d++) {
			if(this.id!=d && pce.getId()!=d) {				
				// pega o melhor tableRow de this para 'd', 'tr'
				TableRow tr = this.getBestMultidomainRow(pt.getDomain(d).getID());
				// pega o tableRow de pce para 'd' que passe por this, 'pceTR'
				TableRow pceTR = null;
				Vector<TableRow> rowVector = pce.getTed().getMultidomainTable().get(pt.getDomain(d));
				for(int i=0; i<rowVector.size(); i++) {
					if(Auxiliar.contains(rowVector.get(i).getPath(), this.id)) {
						pceTR = rowVector.get(i);
						for (int w=0; w<pceTR.getWavelengthsBandwidth().length; w++) {
							// se pceTR.cost(w) > bestTRPceThis.cost(w) + tr.cost(w)
							if (pceTR.getWavelengthAvailableBandwidth(w)>bestTrPceThis.getWavelengthAvailableBandwidth(w)+tr.getWavelengthAvailableBandwidth(w)) {
								pceTR.setCost(w, bestTrPceThis.getCost(w)+tr.getCost(w));
								pceTR.setAvailableWavelength(w, 
										Math.min(bestTrPceThis.getWavelengthAvailableBandwidth(w), tr.getWavelengthAvailableBandwidth(w)));
							}
						}
					}
				}
			}
		}
	}
	
	// 
	/**
	 * atualiza a ted de pce de acordo com a ted de this, agora considerando as porcoes intradomain
	 * 
	 * @param pce
	 */
	public void update2(PCE pce) throws Exception {
		/*   
		pega o tableRow de path.length==1 (para cada borderNode) de pce para this, trPceThis
		pega o melhor tableRow de this para 'd' (para borderNode), 'trThisD'
		para cada pce.tableRow, pceTr
			se pceTr passa por this
				se pceTR.getCost(w)!=bestTrPceThis.getCost(w)+trThisD.getCost(w)
					atualiza
		*/
		
		for(int b=0; b<pt.getNumBorderNodes(pce.getId()); b++) {			
			// pega o tableRow de path.length==1 (para cada borderNode) de pce para this, trPceThis
			TableRow trPceThis = pce.getTed().getShortestMultidomainRow(pt.getBorderNode(pce.getId(), b).getId(), this.id);
			
			for(int d=0; d<pt.getNumDomains(); d++) {
				if(this.id!=d && pce.getId()!=d) {				
					// pega o melhor tableRow de this para 'd' (para borderNode), 'tr'
					TableRow trThisD = this.getBestMultidomainRow(pt.getInBorderNode(pce.getId(), this.id).getId(), pt.getDomain(d).getID());
					if(!Auxiliar.crosses(trThisD.getPath(), pce.getId())) {
						// pega o tableRow de pce para 'd' que passe por this, 'pceTR'
						TableRow trPceD = null;
						Vector<TableRow> rowVector = pce.getTed().getMultidomainTable().get(pt.getDomain(d));
						
						for(int i=0; i<rowVector.size(); i++) {
							trPceD = rowVector.get(i);
							//if( pceTR.getInBorderNode()==pt.getBorderNode(pce.getId(), b).getId() ) {
							int path[] = trPceD.getPath();
							//if( Auxiliar.crosses(trPceD.getPath(), this.id) ) {
							if(path[1]==this.id && trPceD.getInBorderNode()==pt.getBorderNode(pce.getId(), b).getId()) {
									
								for(int w=0; w<trPceD.getWavelengthsBandwidth().length; w++) {
									// se pceTR.cost(w) > bestTRPceThis.cost(w) + trThisD.cost(w)
									if(trPceD.getCost(w)!=trPceThis.getCost(w)+trThisD.getCost(w)) {
										int a[] = new int[1];
										a[0] = path[0];
										trPceD.setPath(Auxiliar.concat2(a, trThisD.getPath()));
										trPceD.setCost(w, trPceThis.getCost(w)+trThisD.getCost(w));
										trPceD.setAvailableWavelength(w, 
												Math.min(trPceThis.getWavelengthAvailableBandwidth(w), trThisD.getWavelengthAvailableBandwidth(w)));
									}
								}								
							}
						}
					}
				}
			}
		}		
	}
	public void updateF(PCE pce) throws Exception {
		/*   
		pega o tableRow de path.length==1 (para cada borderNode) de pce para this, trPceThis
		pega o melhor tableRow de this para 'd' (para borderNode), 'trThisD'
		para cada pce.tableRow, pceTr
			se pceTr passa por this
				se pceTR.getCost(w)!=bestTrPceThis.getCost(w)+trThisD.getCost(w)
					atualiza
		*/
		
		trace.reportUpdateMessage();
		for(int b=0; b<pt.getNumBorderNodes(pce.getId()); b++) {
			// pega o tableRow de path.length==1 (para cada borderNode) de pce para this, trPceThis
			TableRow trPceThis = pce.getTed().getShortestMultidomainRow(pt.getBorderNode(pce.getId(), b).getId(), this.id);
			
			for(int d=0; d<pt.getNumDomains(); d++) {
				if(this.id!=d && pce.getId()!=d) {				
					// pega o melhor tableRow de this para 'd' (para borderNode), 'tr'
					TableRow trThisD = this.getBestMultidomainRow(pt.getInBorderNode(pce.getId(), this.id).getId(), pt.getDomain(d).getID());
					
					if(trThisD!=null && !Auxiliar.crosses(trThisD.getPath(), pce.getId())) {
						// pega o tableRow de pce para 'd' que passe por this, 'pceTR'
						TableRow trPceD = null;
						Vector<TableRow> rowVector = pce.getTed().getMultidomainTable().get(pt.getDomain(d));
						
						for(int i=0; i<rowVector.size(); i++) {
							trPceD = rowVector.get(i);
							int path[] = trPceD.getPath();
							if(path[1]==this.id && trPceD.getInBorderNode()==pt.getBorderNode(pce.getId(), b).getId()) {
								
								for(int w=0; w<trPceD.getWavelengthsBandwidth().length; w++) {
									//if(trPceD.getFreeWavelengths().length!=trPceThis.getFreeWavelengths().length) {
									if(trPceD.getCost(w)!=trPceThis.getCost(w)+trThisD.getCost(w)) {
										int a[] = new int[1];
										a[0] = path[0];
										trPceD.setPath(Auxiliar.concat2(a, trThisD.getPath()));
										trPceD.setFreeWavelengths(Auxiliar.intIntersection(trPceThis.getFreeWavelengths(), trThisD.getFreeWavelengths()));
										trPceD.setCost(w, trPceThis.getCost(w)+trThisD.getCost(w));
										trPceD.setAvailableWavelength(w, 
												Math.min(trPceThis.getWavelengthAvailableBandwidth(w), trThisD.getWavelengthAvailableBandwidth(w)));
									}
								}
							}
						}
					}
				}
			}
		}		
	}
	
	public void update() throws Exception {
		for(int i=0; i<=multidomainTable.size(); i++) {
			Vector<TableRow> tableRowVector = multidomainTable.get(pt.getDomain(i));
			if(tableRowVector!=null) {
				
				for(int j=0; j<tableRowVector.size(); j++) {
					TableRow tableRow = tableRowVector.get(j);
					int[] path = tableRow.getPath();
					WDMLink link = pt.getInterdomainLink(id, path[1]);
					
					for(int k=0; k<tableRow.getWavelengthsBandwidth().length; k++) {
						if(tableRow.getWavelengthAvailableBandwidth(k)!=link.getWavelengthAvailableBandwidth(k)) {
							int dif = (tableRow.getWavelengthAvailableBandwidth(k)-link.getWavelengthAvailableBandwidth(k));
							tableRow.setAvailableWavelength(k, link.getWavelengthAvailableBandwidth(k));							
							tableRow.setCost(k, tableRow.getCost(k)-dif);								
						}
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * @throws Exception
	 */
	public void update2() throws Exception {
		// para cada dominio 'd'
		for(int i=0; i<pt.getNumDomains(); i++) {
			//se 'd' for vizinho de this
			if(pt.areNeighbourDomains(this.id, pt.getDomain(i).getID())){
				
				//pega o menor tableRow entre this e 'd' para cada this.borderNode
				for(int b=0; b<pt.getNumBorderNodes(this.id); b++) {
					TableRow smallestRow = TableRow.getSmallestPath(pt.getBorderNode(this.id, b).getId(), multidomainTable.get(pt.getDomain(i)));
					int dst = pt.getInBorderNode(this.id, pt.getDomain(i).getID()).getId();
					
					// calcula o custo real para 'd'
					WeightedGraph graph = pt.getWeightedGraph();
					int path[] = null;
					do {
						path = Dijkstra.getShortestHopPath(graph, smallestRow.getInBorderNode(), dst);
						if(path!=null && path.length>0 && !pt.isPathEquivalentMultidomainPath(smallestRow.getPath(), path)) {
							int dp[] = pt.getDomainPathFromPath(path);
							WDMLink link2 = pt.getInterdomainLink(this.id, dp[1]);
							graph.removeEdge(link2.getSrcId(), link2.getDstId());
						}
					} while(path!=null && !pt.isPathEquivalentMultidomainPath(smallestRow.getPath(), path));
					int cost[] = pt.getPathWavelengthCost(path, smallestRow.getInBorderNode());
					int wavelength[] = pt.getPathAvailableWavelengths(path, smallestRow.getInBorderNode());
					if(path==null || path.length<=0) {
						break;
					}
					// se o custo real para 'd' (cost) for diferente do custo na tableRow
					for(int j=0; j<cost.length; j++) {
						if(cost[j]!=smallestRow.getCost(j)) {
							int dif = cost[j] - smallestRow.getCost(j);
							
							// para cada dominio
							for(int k=0; k<pt.getNumDomains(); k++) {
								if(this.id!=pt.getDomain(k).getID()) {
									Vector<TableRow> tableRowVector = multidomainTable.get(pt.getDomain(k));
									// para cada tableRow 'tr' de this
									for(int l=0; l<tableRowVector.size(); l++) {
										TableRow tr = tableRowVector.get(l);
										// se tr.path passa pelo vizinho 
										int path2[] = tr.getPath();
										if(tr.getInBorderNode()==pt.getBorderNode(this.id, b).getId() && path2[1]==pt.getDomain(i).getID()) {
											// atualiza na mesma proporcao
											tr.setCost(j, tr.getCost(j)+dif);
											if(dif>0) {
												tr.setAvailableWavelength(j, Math.max(wavelength[j], tr.getWavelengthAvailableBandwidth(j)));
												
											} else {
												tr.setAvailableWavelength(j, Math.min(wavelength[j], tr.getWavelengthAvailableBandwidth(j)));
											}
											
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
	public void updateF() throws Exception {
		// para cada dominio 'd'
		for(int d=0; d<pt.getNumDomains(); d++) {
			//se 'd' for vizinho de this
			if(pt.areNeighbourDomains(this.id, pt.getDomain(d).getID())){
				
				//pega o menor tableRow entre this e 'd' para cada this.borderNode
				for(int b=0; b<pt.getNumBorderNodes(this.id); b++) {
					TableRow smallestRow = TableRow.getSmallestPathF(pt.getBorderNode(this.id, b).getId(), multidomainTable.get(pt.getDomain(d)));
					int dst = pt.getInBorderNode(this.id, pt.getDomain(d).getID()).getId();
					
					// calcula o custo real para 'd'
					WeightedGraph graph = pt.getWeightedGraph();
					int path[] = null;
					do {
						// aqui problema, dijkstra retorna caminho com menos recursos
						path = Dijkstra.getShortestHopPath(graph, smallestRow.getInBorderNode(), dst);
						if(!pt.isPathEquivalentMultidomainPath(smallestRow.getPath(), path)) {
							int dp[] = pt.getDomainPathFromPath(path);
							WDMLink link2 = pt.getInterdomainLink(this.id, dp[1]);
							graph.removeEdge(link2.getSrcId(), link2.getDstId());
						}
					} while(path!=null && !pt.isPathEquivalentMultidomainPath(smallestRow.getPath(), path));
					int cost[] = pt.getPathWavelengthCost(path, smallestRow.getInBorderNode());
					int freeWavelengths[] = pt.getPathFreeWavelengths(path);
					int wavelength[] = pt.getPathAvailableWavelengths(path, smallestRow.getInBorderNode());
					if(path==null || path.length<=0) {
						break;
					}
					// se o custo real para 'd' (cost) for diferente do custo na tableRow
					for(int j=0; j<cost.length; j++) {
						if(cost[j]!=smallestRow.getCost(j)) {
							int dif = cost[j] - smallestRow.getCost(j);
							
							// para cada dominio
							for(int k=0; k<pt.getNumDomains(); k++) {
								if(this.id!=pt.getDomain(k).getID()) {
									Vector<TableRow> tableRowVector = multidomainTable.get(pt.getDomain(k));
									// para cada tableRow 'tr' de this
									TableRow tr;
									for(int l=0; l<tableRowVector.size(); l++) {
										tr = tableRowVector.get(l);
										// se tr.path passa pelo vizinho 
										int path2[] = tr.getPath();
										if(tr.getInBorderNode()==pt.getBorderNode(this.id, b).getId() && path2[1]==pt.getDomain(d).getID()) {
											// atualiza na mesma proporcao
											//if(dif<0 || k==d) {
												tr.setCost(j, tr.getCost(j)+dif);
												//tr.setCost(j, cost[j]);
												if(dif>0) {
													tr.setAvailableWavelength(j, Math.max(wavelength[j], tr.getWavelengthAvailableBandwidth(j)));
													
												} else {
													tr.setAvailableWavelength(j, Math.min(wavelength[j], tr.getWavelengthAvailableBandwidth(j)));
												}
												tr.setFreeWavelengths(freeWavelengths);
												
											//}
										}
										
									}
								}
							}
						}
					}
				}
			}
		}
	}
	
	public int[] getBestMultidomainPathF(int borderNode, int domainId, int resources, Integer wavelength) {
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			
			do {
				tableRow = TableRow.getShortestPathF(tableRowVector, wavelength);
				if(tableRow!=null && tableRow.getWavelengthAvailableBandwidth(wavelength)>=resources && 
						tableRow.getInBorderNode()==borderNode) {
					break;
					
				} else if(tableRow!= null && tableRowVector.contains(tableRow)){
					tableRowVector.remove(tableRow);
					//tableRow = new TableRow(TableRow.getSmallestPath(tableRowVector));
				}		
			} while(tableRow!=null && !tableRowVector.isEmpty());
		}
		System.out.print("");
		if(tableRow==null || tableRowVector.isEmpty())
			return null;
		else 
			return tableRow.getPath();
	
	}
	public int[] getBestMultidomainPathF(int domainId, int resources) {
		int w = -1;
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				
				tableRow = TableRow.getShortestPathF(tableRowVector);
				int i;
				for(i=0; i<pt.getWavelengths(); i++) {
					if(tableRow!=null && tableRow.getWavelengthAvailableBandwidth(i)>=resources) {
						w = i;
						break;
					}
				}
				if(w==-1 || i>=pt.getWavelengths()) {
					if(tableRow!=null && tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(tableRow!=null && w==-1 && !tableRowVector.isEmpty());				
		}
		if(tableRow==null && tableRowVector.isEmpty())
			return null;
		else 
			return tableRow.getPath();
	}
	public TableRow getBestMultidomainRowF(int domainId, int resources) {
		int w = -1;
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				
				tableRow = TableRow.getShortestPathF(tableRowVector);
				int i;
				for(i=0; i<pt.getWavelengths(); i++) {
					if(tableRow!=null && tableRow.getWavelengthAvailableBandwidth(i)>=resources) {
						w = i;
						break;
					}
				}
				if(w==-1 || i>=pt.getWavelengths()) {
					if(tableRow!= null && tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(w==-1 && !tableRowVector.isEmpty() && tableRow!=null);				
		}
		if(tableRowVector.isEmpty() || tableRow==null)
			return null;
		else 
			return tableRow;
	}
	public TableRow getBestMultidomainRowF(int borderNode, int domainId, int resources, Integer wavelength) {
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			
			do {
				tableRow = TableRow.getSmallestPath(tableRowVector, wavelength);
				if(tableRow!= null && tableRow.getWavelengthAvailableBandwidth(wavelength)>=resources && tableRow.getInBorderNode()==borderNode) {
					break;
					
				} else if(tableRow!= null && tableRowVector.contains(tableRow)){
					tableRowVector.remove(tableRow);
					//tableRow = new TableRow(TableRow.getSmallestPath(tableRowVector));
				}		
			} while(tableRow!=null && !tableRowVector.isEmpty());
		}
		
		if(tableRowVector.isEmpty() || tableRow==null)
			return null;
		else 
			return tableRow;
	
	}
	private void generateMultidomainDatabaseF() throws Exception {
		
		//para cada dominio 'd'
		for(int d=0; d<pt.getNumDomains(); d++) {
			int dst = domainVector[d].getID();
			if(dst!=this.id) {
				
				//para cada this.inBorderNode 'ibn'
				int numInBorderNodes = pt.getNumBorderNodes(this.id);
				for(int ibn=0; ibn<numInBorderNodes; ibn++) {
					// calculo o domainPath de this a  'd'
					WeightedGraph graph = pt.getWeightedGraph();
					WeightedGraph domainGraph = pt.getDomainWeightedGraph();
					
					OXC inBorderNode = pt.getBorderNode(this.id, ibn);
					//para cada vizinho
					while(graph.neighbors(inBorderNode.getId()).length>0 && domainGraph.neighbors(this.id).length>0) {
						int[] domainPath = pt.getDomainPath(domainGraph, this.id, dst);
						if(domainPath==null || domainPath.length<=0) {
							break;
						}
						//encontro o link interdomain (domainPath[length], domainPath[length-1])
						WDMLink link = pt.getInterdomainLink(domainPath[domainPath.length-2], domainPath[domainPath.length-1]);
						//encontro o melhor caminho 'path' entre 'ibn' e link.dst
						int path[] = null;
						WeightedGraph graph2 = pt.getWeightedGraph();
						int dp[] = null;
						do {
							path = Dijkstra.getShortestPath(graph2, inBorderNode.getId(), link.getDstId());
							dp = pt.getDomainPathFromPath(path);
							if(dp[1]!=domainPath[1]) {								
								WDMLink link2 = pt.getInterdomainLink(this.id, dp[1]);
								graph2.removeEdge(link2.getSrcId(), link2.getDstId());
							}
						} while(dp!= null && dp[1]!=domainPath[1] && graph.neighbors(this.id).length>0);
						
						if(path==null || path.length<=0) {
							break;
						}
						//encontro os wavelengths desalocados em 'path'
						int[] freeWavelengths = pt.getPathFreeWavelengths(path);
						//encontro a banda disponivel em cada wavelengths de 'path'
						int wavelengthsBandwidth[] = pt.getPathAvailableWavelengths(path, 0);
						//encontro os custos de 'path'
						int costs[] = pt.getPathWavelengthCost(graph, path);
						
						TableRow row = new TableRow(dst, inBorderNode.getId(), freeWavelengths, costs, domainPath, wavelengthsBandwidth);
						addPath(dst, row);
						WDMLink link2 = pt.getInterdomainLink(this.id, domainPath[1]);
						domainGraph.removeEdge(this.id, domainPath[1]);
						graph.removeEdge(link2.getSrcId(), link2.getDstId());
						
					}
				}
			}
		}
	}
	
	/**
	 * 
	 * @param dst: id do dominio destino
	 * @param row
	 */
	public void addPath(int dst, TableRow row) {
		Vector<TableRow> tableRows = new Vector<TableRow>();
		if(multidomainTable.containsKey(pt.getDomain(dst))) {
			// pegar o vector multidomainTable.vector<tableRow>
			// adicionar ao vector o valor de row
			// colocar de volta o novo valor a multidomainTable.vector<tableRow>
			tableRows = multidomainTable.get(pt.getDomain(dst));
			tableRows.add(row);
			
		} else {
			tableRows.add(row);
			multidomainTable.put(pt.getDomain(dst), tableRows);
		}
	}
	
	/**
	 * @throws Exception 
	 * 
	 */
	private void generateMultidomainDatabase() throws Exception {
		int neighbors[];
		// para cada dominio
		for(int i=0; i<pt.getNumDomains(); i++) {	
			int dst = domainVector[i].getID();

			if(dst != this.id) {
				WeightedGraph graph = pt.getDomainWeightedGraph();
				neighbors = graph.neighbors(this.id);
				
				while(graph.neighbors(this.id).length>0) {
					// calcula o menor caminho para dst considerando um simple node abstraction
					int[] domainPath = pt.getDomainPath(graph, this.id, dst);
					if(domainPath==null || domainPath.length<=0) {
						break;
					}
					
					// calcula o enlace com menos bandwidth disponivel em cada wavelength no caminho fim a fim
					int[] wavelengths = pt.getMultidomainAvailableWavelengths(domainPath, 0); 
					// calcula o custo para dst por cada comprimento de onda, considera um simple node abstraction
					int[] costs = pt.getMultidomainWavelengthCost(graph, domainPath, this.id, dst);
					
					TableRow row = new TableRow(dst, costs, domainPath, wavelengths);
					addPath(dst, row);
					graph.removeEdge(this.id, domainPath[1]);
				}
			}
		}
	}

	/**
	 * @throws Exception 
	 * 
	 */
	private void generateMultidomainDatabase2() throws Exception {
		
		//para cada dominio 'd'
		for(int i=0; i<pt.getNumDomains(); i++) {
			int dst = domainVector[i].getID();
			if(dst!=this.id) {
				
				//para cada this.inBorderNode 'ibn'
				int numInBorderNodes = pt.getNumBorderNodes(this.id);
				for(int j=0; j<numInBorderNodes; j++) {
					// calculo o domainPath de this a  'd'
					WeightedGraph graph = pt.getWeightedGraph();
					WeightedGraph domainGraph = pt.getDomainWeightedGraph();
					
					OXC inBorderNode = pt.getBorderNode(this.id, j);
					//para cada vizinho
					while(graph.neighbors(inBorderNode.getId()).length>0 && domainGraph.neighbors(this.id).length>0) {
						int[] domainPath = pt.getDomainPath(domainGraph, this.id, dst);
						if(domainPath==null || domainPath.length<=0) {
							break;
						}
						//encontro o link interdomain (domainPath[length], domainPath[length-1])
						WDMLink link = pt.getInterdomainLink(domainPath[domainPath.length-2], domainPath[domainPath.length-1]);
						//encontro o melhor caminho 'path' entre 'ibn' e link.dst
						int path[] = null;
						WeightedGraph graph2 = pt.getWeightedGraph();
						do {
							path = Dijkstra.getShortestPath(graph2, inBorderNode.getId(), link.getDstId());
							if(!pt.isPathEquivalentMultidomainPath(domainPath, path)) {
								int dp[] = pt.getDomainPathFromPath(path);
								WDMLink link2 = pt.getInterdomainLink(this.id, dp[1]);
								graph2.removeEdge(link2.getSrcId(), link2.getDstId());
							}
						} while(!pt.isPathEquivalentMultidomainPath(domainPath, path) && graph.neighbors(this.id).length>0);
						
						if(path==null || path.length<=0) {
							break;
						}
						//encontro os wavelengths disponiveis em 'path'
						int wavelengths[] = pt.getPathAvailableWavelengths(path, 0);
						//encontro os custos de 'path'
						int costs[] = pt.getPathWavelengthCost(graph, path);
						
						TableRow row = new TableRow(dst, inBorderNode.getId(), costs, domainPath, wavelengths);
						addPath(dst, row);
						WDMLink link2 = pt.getInterdomainLink(this.id, domainPath[1]);
						domainGraph.removeEdge(this.id, domainPath[1]);
						graph.removeEdge(link2.getSrcId(), link2.getDstId());
						
					}
				}
			}
		}
	}
	
	public TableRow getBestMultidomainRow(int domainId) {
		int w = -1;
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			tableRow = TableRow.getSmallestPath2(tableRowVector);
		}
		if(tableRowVector.isEmpty())
			return null;
		else 
			return tableRow;
	}
	
	public TableRow getBestMultidomainRow(int borderNode, int domainId) {
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)(multidomainTable.get(pt.getDomain(domainId)).clone());
			do {
				
				tableRow = TableRow.getSmallestPath2(tableRowVector);
				
				if(tableRow.getInBorderNode()==borderNode) {
					break;
					
				} else {
					tableRowVector.remove(tableRow);
				}	
			} while(!tableRowVector.isEmpty());			
		}
		if(tableRowVector.isEmpty())
			return null;
		else 
			return tableRow;
	}
	
	public TableRow getShortestMultidomainRow(int borderNode, int domainId) {
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)(multidomainTable.get(pt.getDomain(domainId)).clone());
			do {
				
				tableRow = TableRow.getSmallestPath2(tableRowVector);
				
				if(tableRow.getInBorderNode()==borderNode) {
					break;
					
				} else {
					tableRowVector.remove(tableRow);
				}	
			} while(!tableRowVector.isEmpty());			
		}
		if(tableRowVector.isEmpty())
			return null;
		else 
			return tableRow;
	}
	
	/**
	 * Verifica na tabela de roteamento se ha caminho entre seu dominio e o dominio 
	 * domainId com quantidade de recursos maior ou igual a resources 
	 * 
	 * @param domainId
	 * @param resources
	 * @return
	 */
	public int[] getBestMultidomainPath(int domainId, int resources) {
		int w = -1;
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				
				tableRow = TableRow.getSmallestPath(tableRowVector);
				int i;
				for(i=0; i<pt.getWavelengths(); i++) {
					if(tableRow.getWavelengthAvailableBandwidth(i)>=resources) {
						w = i;
						break;
					}
				}
				if(w==-1 || i>=pt.getWavelengths()) {
					if(tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(w==-1 && !tableRowVector.isEmpty());				
		}
		if(tableRowVector.isEmpty())
			return null;
		else 
			return tableRow.getPath();
	}
	public int[] getBestMultidomainPath2(int domainId, int resources) {
		int w = -1;
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				
				tableRow = TableRow.getSmallestPath(tableRowVector);
				int i;
				for(i=0; i<pt.getWavelengths(); i++) {
					if(tableRow.getWavelengthAvailableBandwidth(i)==2480) {
						w = i;
						break;
					}
				}
				if(w==-1 || i>=pt.getWavelengths()) {
					if(tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(w==-1 && !tableRowVector.isEmpty());				
		}
		if(tableRowVector.isEmpty())
			return null;
		else 
			return tableRow.getPath();
	}
	
	// retorna um tableRow com wavelength com recources suficientes
	public int[] getBestMultidomainPath(int domainId, int resources, Integer wavelength) {
			Vector<TableRow> tableRowVector = null;
			TableRow tableRow = null;
			
			if(multidomainTable.containsKey(pt.getDomain(domainId))) {
				tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
				
				do {
					tableRow = (TableRow.getSmallestPath(tableRowVector, wavelength));
					if(tableRow.getWavelengthAvailableBandwidth(wavelength)>=resources) {
						break;
						
					} else if(tableRowVector.contains(tableRow)){
						tableRowVector.remove(tableRow);
					}		
				} while(!tableRowVector.isEmpty());
			}
			
			if(tableRowVector.isEmpty())
				return null;
			else 
				return tableRow.getPath();
		
	}
	
	// retorna um tableRow com wavelength com recources suficientes e inBorderNode = borderNode
	public int[] getBestMultidomainPath(int borderNode, int domainId, int resources, Integer wavelength) {
			Vector<TableRow> tableRowVector = null;
			TableRow tableRow = null;
			
			if(multidomainTable.containsKey(pt.getDomain(domainId))) {
				tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
				
				do {
					tableRow = TableRow.getSmallestPath(tableRowVector, wavelength);
					if(tableRow.getWavelengthAvailableBandwidth(wavelength)>=resources && tableRow.getInBorderNode()==borderNode) {
						break;
						
					} else if(tableRowVector.contains(tableRow)){
						tableRowVector.remove(tableRow);
						//tableRow = new TableRow(TableRow.getSmallestPath(tableRowVector));
					}		
				} while(!tableRowVector.isEmpty());
			}
			
			if(tableRowVector.isEmpty())
				return null;
			else 
				return tableRow.getPath();
		
	}
	
	public Vector<Integer> getMultidomainCandidateWavelengths(int domainId, int resources) {
		Vector<Integer> w = new Vector<Integer>();
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				tableRow = TableRow.getSmallestPath(tableRowVector);
				for(int i=0; i<pt.getWavelengths(); i++) {
					if(tableRow.getWavelengthAvailableBandwidth(i)>=resources) {
						w.add(i);
					}
				}
				if(w.size()==0) {
					if(tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(w.size()==0 && !tableRowVector.isEmpty());				
		}
		return w;
	}
	
	public Vector<Integer> getMultidomainCandidateWavelengths(int domainId, int src, int resources) throws Exception {
		WeightedGraph graph = null;
		Vector<Integer> w = new Vector<Integer>();
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				tableRow = TableRow.getSmallestPath(tableRowVector);
				if(src!=tableRow.getInBorderNode()) {
					int path[] = null;
					graph = pt.getIntradomainWeightedGraph(this.id);
					do {
						path = Dijkstra.getShortestPath(graph, src, tableRow.getInBorderNode());
						int intradomainAvailability[] = pt.getPathWavelengthAvailability(graph, path, src);
					
						for(int i=0; i<pt.getWavelengths(); i++) {
							if(tableRow.getWavelengthAvailableBandwidth(i)>=resources && 
									intradomainAvailability[i]>=resources) {
								w.add(i);
							}
						}
						if(w.size()==0 && path!=null && path.length>0) {
							// delete any edge of path
							// random variable between 1 and i+1 (Min + (int)(Math.random() * ((Max - Min) + 1)))
							int i2 = (1 + (int)(Math.random() * (((path.length-1) - 1) + 1)));
							int i1 = i2-1;
							graph.removeEdge(path[i1], path[i2]);
						}
					} while(w.size()==0 && path!=null && path.length>0);
				}
				if(w.size()==0) {
					if(tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}				
			} while(w.size()==0 && !tableRowVector.isEmpty());
			System.out.println();
		}
		return w;
	}
	public Vector<Integer> getMultidomainCandidateWavelengths2(int domainId, int src, int resources) throws Exception {
		WeightedGraph graph = pt.getIntradomainWeightedGraph(this.id);
		Vector<Integer> w = new Vector<Integer>();
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				tableRow = TableRow.getSmallestPath(tableRowVector);
				int path[] = Dijkstra.getShortestPath(graph, src, tableRow.getInBorderNode());
				int intradomainAvailability[] = pt.getPathWavelengthAvailability(graph, path, src);
				for(int i=0; i<pt.getWavelengths(); i++) {
					if(tableRow.getWavelengthAvailableBandwidth(i)==2480 && 
							intradomainAvailability[i]>=resources) {
						w.add(i);
					}
				}
				if(w.size()==0) {
					if(tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(w.size()==0 && !tableRowVector.isEmpty());				
		}
		return w;
	}
	
	public int getBestMultidomainWavelength(int domainId, int resources) {
		int w = -1;
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			do {
				tableRow = TableRow.getSmallestPath(tableRowVector);
				for(int i=0; i<pt.getWavelengths(); i++) {
					if(tableRow.getWavelengthAvailableBandwidth(i)>=resources) {
						w = i;
						break;
					}
				}
				if(w==-1) {
					if(tableRowVector.contains(tableRow)) {
						tableRowVector.remove(tableRow);
					}
				}	
			} while(w==-1 && !tableRowVector.isEmpty());				
		}
		return w;
	}

	/**
	 * @param prohibitedDomain
	 * @param borderNode
	 * @param id2
	 * @param bw
	 * @param wavelength
	 * @return
	 */
	public int[] getBestMultidomainPathF(Vector<Integer> bedDomains, int borderNode, int domainId, int resources, Integer wavelength) {
		Vector<TableRow> tableRowVector = null;
		TableRow tableRow = null;
		
		if(multidomainTable.containsKey(pt.getDomain(domainId))) {
			tableRowVector = (Vector<TableRow>)multidomainTable.get(pt.getDomain(domainId)).clone();
			
			do {
				tableRow = TableRow.getShortestPathF(tableRowVector, wavelength);
				if(tableRow!=null && tableRow.getWavelengthAvailableBandwidth(wavelength)>=resources && 
						tableRow.getInBorderNode()==borderNode && !bedDomains.contains(tableRow.getPath(1))) {
					break;
					
				} else if(tableRow!= null && tableRowVector.contains(tableRow)){
					tableRowVector.remove(tableRow);
					//tableRow = new TableRow(TableRow.getSmallestPath(tableRowVector));
				}		
			} while(tableRow!=null && !tableRowVector.isEmpty());
		}
		System.out.print("");
		if(tableRow==null || tableRowVector.isEmpty())
			return null;
		else 
			return tableRow.getPath();
	}
		
	/**
	 * @throws Exception 
	 * 
	 */
	/*private void generateIntradomainDatabase() throws Exception {
		
		PhysicalTopology pt = PhysicalTopology.getInstance();		
		//boolean[][] adjDomainMatrix = pt.getAdjacencyDomainMatrix();
		WeightedGraph graph = new WeightedGraph(pt.getNumNodes());
		
		for(int i=0; i<pt.getNumNodes(); i++) {
			for(int j=0; j<pt.getNumNodes(); j++ ) {
				
				if(i!=j && pt.belongsSameDomain(i, j) && pt.getNode(i).getDomainID()==this.id) {
					Dijkstra disjkstra = new Dijkstra();
					int cost = 0;
					int path[] = null; 
					//intradomainTable.add(new TableRow(id, cost, path));
					//intradomainTable.add(i, TableRow(c,p))
				}
			}
		}
	}
	// funçao que retorna se hs caminho interno atr borderNode
	public int[] getBestIntradomainPath(int inNodeId, int outNodeId) {
		return new int[5];
	}*/
}
